package lab.dexter.bbsreader.managers;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import lab.dexter.bbsreader.ListBrowser;
import lab.dexter.bbsreader.ListManager;
import lab.dexter.bbsreader.NewSMTHHttpClient;

import org.apache.http.HttpEntity;
import org.apache.http.ParseException;

import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import lab.dexter.bbsreader.R;

public class BoardPostsManager extends ListManager {
	public static final String PARAM_BOARD = "BOARD_NAME";
	public static final String PARAM_VIEW_MODE = "BOARD_VIEW_MODE";
	
	public static final int PARAM_VIEW_MODE_NORMAL = 0;
	public static final int PARAM_VIEW_MODE_TOPIC = 1;
	
	private class PostItem {
		public int number;
		public String id;
		public String user;
		public String timestamp;
		public String title;
		public String flag;
		
		public PostItem(String number_, String id_, String user_, String timestamp_, String title_, String flag_) {
			if(number_.contains("[")) {
				number = Integer.MAX_VALUE;
			}
			else {
				number_ = number_.trim();
				if(number_.indexOf('m') != -1
						|| number_.indexOf('g') != -1 
						|| number_.indexOf('b') != -1) {
					flag = number_.charAt(number_.length() - 1) + "";
					number_ = number_.substring(0, number_.length() - 1);
				}
				number = Integer.parseInt(number_);
			}
			id = id_;
			user = user_;
			timestamp = timestamp_;
			title = title_;
			flag += flag_;
		}
		
		public boolean isHeadPost() {
			return title.startsWith("●");
		}
	}
	
	public int startTopicInfo;
	public int totalTopicInfo;
	public int pageTopicInfo;
	
	private String boardName;
	
	private Pattern patternPostNormal;
	private Pattern patternNextNormal;
	private Pattern patternPostTopic;
	private Pattern patternPageTopic;
	
	private List<PostItem> posts;
	private String nextTarget;
	
	private boolean loadButtonEnabled;
	private int viewMode;
	
	private final String TARGET_PREFIX_NORMAL = "http://www.newsmth.net/atomic2.php?act=board&board=";
	private final String TARGET_PREFIX_TOPIC = "http://www.newsmth.net/bbsdoc.php?ftype=6&board=";
	
	private final String REGEXP_POST_NORMAL = "<tr\\s+class=\"?bgf\"?><td>(.*?)</td><td><a\\s+href=\"(.*?)\">(.*?)</a></td><td>(.*?)</td><td\\s+align=left>(.*?)\\s+<a\\s+href='(.*?)'>(.*?)</a></td></tr>";
	private final String REGEXP_NEXT_NORMAL = "<a\\s+href=\"([^>]+)\">上页</a>";
	private final String REGEXP_POST_TOPIC = "c.o\\((.+?),(.+?),'(.+?)','(.+?)',(.+?),'(.+?)',.+?\\)";
	private final String REGEXP_PAGE_TOPIC = "var c = new docWriter\\(.+?,.+?,(.+?),.+?,.+?,(.+?),(.+?),.+?\\)";
	
	
	public BoardPostsManager(Context context, Intent intent) {
		super(context, intent);
		boardName = intent.getStringExtra(PARAM_BOARD);
		viewMode = intent.getIntExtra(PARAM_VIEW_MODE, 0);
		
		patternPostTopic = Pattern.compile(REGEXP_POST_TOPIC);
		patternPageTopic = Pattern.compile(REGEXP_PAGE_TOPIC);
		
		patternPostNormal = Pattern.compile(REGEXP_POST_NORMAL);
		patternNextNormal = Pattern.compile(REGEXP_NEXT_NORMAL);
		
		posts = new ArrayList<PostItem>();
		loadButtonEnabled = false;
		
		switch(viewMode) {
		case PARAM_VIEW_MODE_NORMAL:
			nextTarget = TARGET_PREFIX_NORMAL + boardName;
			break;
		case PARAM_VIEW_MODE_TOPIC:
			nextTarget = TARGET_PREFIX_TOPIC + boardName;
			break;
		}
	}

	@Override
	public boolean onItemClick(int position) {
		if(position >= posts.size() && loadButtonEnabled) {
			// in case user hit the button repeatedly
			loadButtonEnabled = false;
			return true; // update is needed
		}
		Intent intent = new Intent(mContext, ListBrowser.class);
		intent.setAction(Intent.ACTION_VIEW);
		intent.putExtra(ListBrowser.MGR, ListBrowser.MGR_POST);
		intent.putExtra(PostManager.PARAM_BOARD, this.boardName);
		intent.putExtra(PostManager.PARAM_INITIAL_ID, posts.get(position).id);
		mContext.startActivity(intent);
		return false;
	}

	@Override
	public int update() {
		try {
			NewSMTHHttpClient.getClient().fetchData(nextTarget, this);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return 0;
	}
	
	private void dataProcessorNormal(String target) {
		Matcher matcher = patternPostNormal.matcher(target);

		List<PostItem> currentList = new ArrayList<PostItem>();
		while(matcher.find()) {
			String number = matcher.group(1);
			String user = matcher.group(3);
			String timestamp = matcher.group(4);
			String flag = matcher.group(5); // such as @
			String post_link = matcher.group(6);
			String title = matcher.group(7);
			String id = post_link.substring(post_link.lastIndexOf('=') + 1);
			currentList.add(new PostItem(number, id, user, timestamp, title, flag));
		}
		Collections.reverse(currentList);
		int last = Integer.MAX_VALUE;
		if(posts.size() > 0) {
			last = posts.get(posts.size() - 1).number;
			for(int i = 0; i < currentList.size(); i ++) {
				if(currentList.get(i).number < last) {
					currentList = currentList.subList(i, currentList.size());
					break;
				}
			}
		}
		posts.addAll(currentList);
		
		// can't do this in another thread
//		if(posts.size() == 0) {
//			// Something wrong with the board name
//			Toast.makeText(mContext.getApplicationContext(), "Cannot open board " + boardName, Toast.LENGTH_SHORT);
//		}
		
		matcher = patternNextNormal.matcher(target);
		if(matcher.find()) {
			nextTarget = TARGET_PREFIX_NORMAL + boardName + "&page=" + matcher.group(1);
		}
	}
	
	private void dataProcessorTopic(String target) {
		Log.v("target", target);
		// parse meta information
		Matcher matcher = patternPageTopic.matcher(target);
		if(matcher.find()) {
			startTopicInfo = Integer.parseInt(matcher.group(1));
			pageTopicInfo = Integer.parseInt(matcher.group(2));
			totalTopicInfo = Integer.parseInt(matcher.group(3));
		}
		else {
			return;
		}

		// parse titles
		// REGEXP_POST_TOPIC = "c.o\\((.+?),(.+?),'(.+?)','(.+?)',(.+?),'(.+?)',.+?\\)";
		//                           (id 1, gid 2, author 3, flag 4, time 5, title 6, size, imported, is_tex)
		matcher = patternPostTopic.matcher(target);
		List<PostItem> currentList = new ArrayList<PostItem>();
		int counter = 0;
		while(matcher.find()) {
			int number  = counter + startTopicInfo;
			String id = matcher.group(1);
			String user = matcher.group(3);
			String flag = matcher.group(4);
			String time = matcher.group(5);
			String title = matcher.group(6);
			Date date = new Date((Long.parseLong(time)+8*3600) * 1000);
			DateFormat df = new SimpleDateFormat("MMM d");
			currentList.add(new PostItem(Integer.toString(number), id, user, df.format(date), title, flag));
			counter ++;
		}
		Collections.reverse(currentList);
		if(posts.size() > 0) {
			int last = posts.get(posts.size() - 1).number;
			for(int i = 0; i < currentList.size(); i ++) {
				if(currentList.get(i).number < last) {
					currentList = currentList.subList(i, currentList.size());
					break;
				}
			}
		}
		posts.addAll(currentList);
		
		nextTarget = TARGET_PREFIX_TOPIC + boardName + "&page=" + (pageTopicInfo - 1); 
	}

	public void dataProcessor(HttpEntity entity) {
		try {
			// stupid server massed up the charset header, so we do the decoding manually
			//content = EntityUtils.toString(entity);
			BufferedReader reader = null;
			switch(viewMode) {
			case PARAM_VIEW_MODE_NORMAL:
				reader = new BufferedReader(new InputStreamReader(entity.getContent(), "UTF-8"));
				break;
			case PARAM_VIEW_MODE_TOPIC:
				reader = new BufferedReader(new InputStreamReader(entity.getContent(), "GBK"));
				break;
			}
			StringBuilder builder = new StringBuilder();
			String line = null;
			while((line = reader.readLine()) != null) {
				builder.append(line);
			}
			String target = builder.toString();
			
			switch(viewMode) {
			case PARAM_VIEW_MODE_NORMAL:
				dataProcessorNormal(target);
				break;
			case PARAM_VIEW_MODE_TOPIC:
				dataProcessorTopic(target);
				break;
			}
			
		} catch (ParseException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// update finished, now we can re-enable the load button at the end of the list
		loadButtonEnabled = true;
	}

	public boolean areAllItemsEnabled() {
		return false;
	}

	public boolean isEnabled(int position) {
		if(position >= posts.size() && !loadButtonEnabled) {
			return false;
		}
		return true;
	}

	public int getCount() {
		return posts.size() + 1;
	}

	public Object getItem(int position) {
		return posts.get(position);
	}

	public long getItemId(int position) {
		return position;
	}

	public int getItemViewType(int position) {
		if(position >= posts.size()) {
			return 1;
		}
		return 0;
	}

	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO: put flags somewhere
		View view = convertView;
		if(position >= posts.size()) {
			if(view == null) {
				LayoutInflater vi = (LayoutInflater)(mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE));
				view = vi.inflate(android.R.layout.simple_list_item_1, null);
			}
			TextView tv = (TextView)view.findViewById(android.R.id.text1);
			tv.setText("(View more posts ...)");
		}
		else {
			if(view == null) {
				LayoutInflater vi = (LayoutInflater)(mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE));
				view = vi.inflate(R.layout.double_row_topic_item, null);
			}
			PostItem it = posts.get(position);
			if(it != null) {
				TextView tv = (TextView)view.findViewById(R.id.title);
				
				if (tv != null) {
					tv.setText(it.title);
				}
				
				TextView meta = (TextView)view.findViewById(R.id.meta_info);
				
				if (meta != null) {
					String num;
					if(it.number == Integer.MAX_VALUE) {
						num = "[提示]";
					} else {
						num = Integer.toString(it.number);
					}
					meta.setText(num + " by " + it.user + " at " + it.timestamp);
				}
			}
		}
		return view;
	}

	public int getViewTypeCount() {
		return 2;
	}
	
	@Override
	public String getTitleSuffix() {
		String prefix;
		if(viewMode == PARAM_VIEW_MODE_NORMAL) {
			prefix = "普通模式";
		}
		else {
			prefix = "同主题";
		}
		return prefix + " " + boardName;
	}
	
	@Override
	public int getContextMenuResource() {
		return R.menu.board_posts_context_menu;
	}
	
	@Override
	public boolean hasContextMenu() {
		return true;
	}
	
	@Override
	public void onContextItemSelected(MenuItem item) {
		int id = item.getItemId();
		//String text = null;
		switch(id) {
		case R.id.switch_mode:
			int targetMode;
			if(viewMode == PARAM_VIEW_MODE_TOPIC) {
				targetMode = PARAM_VIEW_MODE_NORMAL;
			}
			else {
				targetMode = PARAM_VIEW_MODE_TOPIC;
			}
			
			Intent intent = new Intent(mContext, ListBrowser.class);
			intent.setAction(Intent.ACTION_VIEW);
			intent.putExtra(ListBrowser.MGR, ListBrowser.MGR_BOARD_POSTS);
			intent.putExtra(BoardPostsManager.PARAM_BOARD, boardName);
			intent.putExtra(BoardPostsManager.PARAM_VIEW_MODE, targetMode);
			mContext.startActivity(intent);
			break;
		}
		//Toast.makeText(mContext.getApplicationContext(), text, Toast.LENGTH_SHORT).show();
	}
	
}
